/**
 * ---------------------------
 * Time: 2017/8/9 16:22.
 * Author: Cangshi
 * View: http://palerock.cn
 * ---------------------------
 */
define(['app'], function (app) {

    /**
     * 实体对象-设备{Device}
     */
    app.factory('Device', function (ArrayUtils, MaintainPlan, RunningRecord, DateTimeUtils, ObjectUtils, logger, RepairRecord) {
        var Device = function (device) {
            this.deviceNo = null;
            this.deviceName = null;
            this.deviceDiscription = null;
            this.runningDuration = 0;
            this.maxPercentage = 0.0;
            this.registerInfo = {};
            this.maintainPlans = [];
            this.repairRecords = [];
            this.runningRecords = [];
            this.memorandum = {
                exist: false,
                content: ''
            };
            if (device) {
                this._register(device);
            }
        };
        Device.prototype = {
            constructor: Device,
            /**
             * 注册设备，构造方法调用
             * @param device
             * @returns {Device}
             */
            _register: function (device) {
                this.deviceNo = device.deviceNo;
                this.deviceName = device.deviceName;
                this.deviceDiscription = device.deviceDiscription;
                this.registerInfo = device.registerInfo;
                this.runningDuration = device.registerInfo.usedDuration;
                this.registerInfo.registerTime = new Date();
                this.maintainPlans = device.maintainPlans;
                return this;
            },
            /**
             * 刷新设备的信息
             */
            refreshInfo: function () {
                if (!this.memorandum) {
                    this.memorandum = {
                        exist: false,
                        content: ''
                    }
                }
                var runningTime = 0;
                if (this.registerInfo.usedDuration) {
                    runningTime += this.registerInfo.usedDuration;
                }
                // 获取运行记录中的信息
                ArrayUtils.ergodicArrayObject(this, this.runningRecords, function (value) {
                    if (typeof value.recordChangedDuration != 'number') {
                        var duration = parseInt(value.recordChangedDuration);
                        if (!Number.isNaN(duration)) {
                            runningTime += duration;
                        }
                    } else {
                        runningTime += value.recordChangedDuration;
                    }
                });
                this.runningDuration = runningTime;
                var maintainMaxPercentages = [];
                ArrayUtils.ergodicArrayObject(this, this.maintainPlans, function (maintainPlan) {
                    if (!(maintainPlan instanceof MaintainPlan)) {
                        maintainPlan = ObjectUtils.toAimObject(maintainPlan, MaintainPlan);
                    }
                    maintainPlan._refreshInfo(this);
                    maintainMaxPercentages.push(maintainPlan.currentMaxPercentage)
                });
                this.maxPercentage = Math.max.apply(this, maintainMaxPercentages);
            },
            /**
             * 添加一条运行记录
             * @param recordChangedDuration {number} 运行时长
             */
            addRunningRecord: function (recordChangedDuration) {
                this.refreshInfo();
                var runningRecord = new RunningRecord({
                    recordId: DateTimeUtils.getCurrentId(),
                    runningDurationBeforeRunning: this.runningDuration,
                    recordChangedDuration: recordChangedDuration
                });
                this.runningRecords.push(runningRecord);
                this.refreshInfo();
            },
            /**
             * 获取该设备的统计信息
             */
            generateStatistics: function () {
                this.refreshInfo();
                // 默认统计信息模板
                var defaultStatistics = {
                    running: {
                        // 距离注册到现在的天数
                        daysSinceRegistered: 0,
                        // 日均运行时长
                        dailyAverage: 0,
                        // 月均运行时长
                        monthlyAverage: 0,
                        // 年均运行时长
                        annualAverage: 0,
                        // 当月运行总时长
                        totalInMonth: 0,
                        // 当年运行总时长
                        totalInYear: 0
                    },
                    repair: {
                        // 当年总维修次数
                        totalInMonth: 0,
                        // 当月总维修次数
                        totalInYear: 0,
                        // 总维修次数
                        totalTimes: this.repairRecords.length,
                        // 月度维修率(总月数/总维修次数)
                        monthlyRate: 0,
                        // 年度维修率(总年数/总维修次数)
                        annuallyRate: 0,
                        // 当年维修总支出
                        totalCostInYear: 0,
                        // 当月维修总支出
                        totalCostInMonth: 0,
                        // 维修总支出
                        totalCost: 0,
                        // 维修总耗用时间
                        totalCostTime: 0
                    },
                    maintain: {
                        // 总保养次数
                        totalTimes: 0,
                        // 各级保养统计数据
                        maintainsStatistics: []
                    },
                    total: {
                        // 设备开机率
                        bootRate: 0,
                        // 设备故障率
                        failureRate: 0
                    }
                };
                var statistics = {
                    deviceNo: this.deviceNo,
                    deviceName: this.deviceName,
                    deviceDiscription: this.deviceDiscription,
                    statistics: defaultStatistics
                };

                // 得到运行统计数据
                defaultStatistics.running = RunningRecord.generateRunningStatistics(this);
                // 得到维修统计数据
                defaultStatistics.repair = RepairRecord.generateRepairStatistics(this);
                // 计算保养统计数据
                ArrayUtils.ergodicArrayObject(this, this.maintainPlans, function (maintainPlan) {
                    var statistics = maintainPlan.generateMaintainStatistics(this);
                    defaultStatistics.maintain.totalTimes += statistics.totalTimes;
                    defaultStatistics.maintain.maintainsStatistics.push(statistics);
                });

                // 设定开机率
                defaultStatistics.total.bootRate = (this.runningDuration - this.registerInfo.usedDuration) / (
                    DateTimeUtils.getNowBetweenADay(
                        this.registerInfo.registerTime, true
                    ) * 24);
                // 设定故障率
                defaultStatistics.total.failureRate = this.runningDuration ?
                defaultStatistics.repair.totalCostTime / this.runningDuration : 0;

                return statistics;
            }
        };
        /**
         * 转换对象为Device
         * @param obj
         * @returns {*}
         */
        Device.toDevice = function (obj) {
            return ObjectUtils.toAimObject(obj, Device);
        };
        /**
         * 判断对象是否是设备
         * @param device
         * @returns {boolean}
         */
        Device.isDevice = function (device) {
            return device instanceof Device;
        };
        /**
         * 通过设备列表生成统计数据
         * @param devices
         */
        Device.generateStatistics = function (devices) {
            if (!ArrayUtils.isArrayObject(devices)) {
                logger.warn('被统计的设备列表必须是一个数组');
                return;
            }
            var allStatistics = [];
            ArrayUtils.ergodicArrayObject(this, devices, function (device) {
                if (this.isDevice(device)) {
                    var statistics = device.generateStatistics();
                    allStatistics.push(statistics);
                }
            });
            // 总统计数据的提取
            var temp = ObjectUtils.parseTheSameObjectAllPropertyInArray(allStatistics);
            if (temp) {
                // 获取计算和的属性
                var sum = ObjectUtils.getCalculationInArrayByLinkPropertyNames(temp, [
                    'statistics.maintain.totalTimes',
                    'statistics.maintain.maintainsStatistics.0.totalTimes',
                    'statistics.maintain.maintainsStatistics.1.totalTimes',
                    'statistics.maintain.maintainsStatistics.2.totalTimes',
                    'statistics.maintain.maintainsStatistics.0.totalInYear',
                    'statistics.maintain.maintainsStatistics.1.totalInYear',
                    'statistics.maintain.maintainsStatistics.2.totalInYear',
                    'statistics.maintain.maintainsStatistics.0.totalInMonth',
                    'statistics.maintain.maintainsStatistics.1.totalInMonth',
                    'statistics.maintain.maintainsStatistics.2.totalInMonth',
                    'statistics.repair.totalCostInYear',
                    'statistics.repair.totalCostInMonth',
                    'statistics.repair.totalTimes',
                    'statistics.repair.totalInMonth',
                    'statistics.repair.totalInYear',
                    'statistics.repair.totalCost',
                    'statistics.repair.totalCostTime'
                ], 'sum');
                // 获取计算平均值的属性
                var average = ObjectUtils.getCalculationInArrayByLinkPropertyNames(temp, [
                    'statistics.maintain.maintainsStatistics.0.monthlyAverageTimes',
                    'statistics.maintain.maintainsStatistics.1.monthlyAverageTimes',
                    'statistics.maintain.maintainsStatistics.2.monthlyAverageTimes',
                    'statistics.maintain.maintainsStatistics.0.annualAverageTimes',
                    'statistics.maintain.maintainsStatistics.1.annualAverageTimes',
                    'statistics.maintain.maintainsStatistics.2.annualAverageTimes',
                    'statistics.total.bootRate',
                    'statistics.total.failureRate',
                    'statistics.running.dailyAverage',
                    'statistics.running.monthlyAverage',
                    'statistics.running.annualAverage',
                    'statistics.repair.monthlyRate',
                    'statistics.repair.annuallyRate'
                ], 'average');

                // 合并统计
                allStatistics.totalStatistics = ObjectUtils.expandObject(sum, average, false, true);

                // allStatistics.totalStatistics = {
                //     running: {
                //         // 总开机率
                //         bootRate: ArrayUtils.getAverageInArray(temp.statistics.total.bootRate),
                //         // 总故障率
                //         failureRate: ArrayUtils.getAverageInArray(temp.statistics.total.failureRate),
                //         // 总日均运行时长
                //         dailyAverage: ArrayUtils.getAverageInArray(temp.statistics.running.dailyAverage),
                //         // 总月均运行时长
                //         monthlyAverage: ArrayUtils.getAverageInArray(temp.statistics.running.monthlyAverage),
                //         // 总年均运行时长
                //         annualAverage: ArrayUtils.getAverageInArray(temp.statistics.running.annualAverage)
                //     },
                //     maintain: {
                //         // 所有设备总保养次数
                //         totalTimes: ArrayUtils.getSumInArray(temp.statistics.maintain.totalTimes),
                //         // 所有设备各级保养统计数据（统计1-3级）
                //         maintainsStatistics: []
                //     },
                //     repair: {
                //         // 当年所有设备总维修次数
                //         totalInMonth: ArrayUtils.getSumInArray(temp.statistics.repair.totalInMonth),
                //         // 当月所有设备总维修次数
                //         totalInYear: ArrayUtils.getSumInArray(temp.statistics.repair.totalInYear),
                //         // 所有设备总维修次数
                //         totalTimes: ArrayUtils.getSumInArray(temp.statistics.repair.totalTimes),
                //         // 所有设备月度维修率均值
                //         monthlyRate: ArrayUtils.getAverageInArray(temp.statistics.repair.monthlyRate),
                //         // 所有设备年度维修率均值
                //         annuallyRate: ArrayUtils.getAverageInArray(temp.statistics.repair.annuallyRate),
                //         // 当年所有设备维修总支出
                //         totalCostInYear: ArrayUtils.getSumInArray(temp.statistics.repair.totalCostInYear),
                //         // 当所有设备月维修总支出
                //         totalCostInMonth: ArrayUtils.getSumInArray(temp.statistics.repair.totalCostInMonth),
                //         // 所有设备维修总支出
                //         totalCost: ArrayUtils.getSumInArray(temp.statistics.repair.totalCost),
                //         // 所有设备维修总耗用时间
                //         totalCostTime: ArrayUtils.getSumInArray(temp.statistics.repair.totalCostTime)
                //     }
                // };
            }
            return allStatistics;
        };

        return Device;
    });

    /**
     * 实体对象-保养计划实体（单个） {MaintainPlan}
     */
    app.factory('MaintainPlan', function (ObjectUtils, ArrayUtils, MaintainRecord, DateTimeUtils, logger) {
        var MaintainPlan = function (maintainPlan) {
            this.maintainName = null;
            // 保养需求(运行时长)
            this.limitingConditionFromRunningDuration = null;
            // 保养需求(运行天数)
            this.limitingConditionFromDaysNumber = null;
            this.maintainContent = null;
            this.lastMaintainInfo = null;
            this.currentRunningDuration = 0;
            this.currentMaxPercentage = 0.00;
            this.currentDaysConsumedNumber = 0;
            this.maintainRecords = [];
            if (maintainPlan) {
                this._initMaintainPlan(maintainPlan);
            }
        };
        MaintainPlan.prototype = {
            constructor: MaintainPlan,
            _initMaintainPlan: function (maintainPlan) {
                this.maintainName = maintainPlan.maintainName;
                this.limitingConditionFromRunningDuration = maintainPlan.limitingConditionFromRunningDuration;
                this.limitingConditionFromDaysNumber = maintainPlan.limitingConditionFromDaysNumber;
                this.maintainContent = maintainPlan.maintainContent;
            },
            /**
             * 获取上次保养的信息
             * @returns {*}
             * @private
             */
            _getLastMaintainInfo: function () {
                if (this.lastMaintainInfo) {
                    return this.lastMaintainInfo;
                }
                var length = this.maintainRecords.length;
                if (length < 1) {
                    return null;
                }
                return this.maintainRecords[0];
            },
            /**
             * 生成距离上次保养经过的时长
             * @param parentDevice
             * @private
             */
            _buildCurrentRunningDuration: function (parentDevice) {
                // 获取上次保养的记录
                var lastMaintainInfo = this._getLastMaintainInfo();
                // 获取设备总时长
                var runningDuration = parentDevice.runningDuration ? parentDevice.runningDuration : 0;
                // 获取设备注册时填写的已用时长
                var originDuration = parentDevice.registerInfo.usedDuration;
                // 获取设备的运行记录
                // 判断父级设备的运行记录存在或是不是为空
                if (!lastMaintainInfo || !lastMaintainInfo.runningDurationWhileMaintaining) {
                    if (originDuration && typeof originDuration == 'number') {
                        this.currentRunningDuration = runningDuration - originDuration;
                    } else {
                        this.currentRunningDuration = runningDuration;
                    }
                    return this.currentRunningDuration;
                }
                // 获取上一次设备运行的记录
                this.currentRunningDuration = runningDuration - lastMaintainInfo.runningDurationWhileMaintaining;
                return this.currentRunningDuration;
            },
            /**
             * 生成当前距上次保养经过的天数
             * @param parentDevice
             * @returns {*|number}
             * @private
             */
            _buildCurrentDaysConsumedNumber: function (parentDevice) {
                // 获取上一次保养的记录
                var lastMaintainInfo = this._getLastMaintainInfo();
                if (!lastMaintainInfo || !lastMaintainInfo.recordTime) {
                    this.currentDaysConsumedNumber = DateTimeUtils.getNowBetweenADay(parentDevice.registerInfo.registerTime);
                } else {
                    this.currentDaysConsumedNumber = DateTimeUtils.getNowBetweenADay(lastMaintainInfo.recordTime);
                }
                return this.currentDaysConsumedNumber;
            },
            /**
             * 根据记录刷新信息
             * @param parentDevice
             * @private
             */
            _refreshInfo: function (parentDevice) {
                this._buildCurrentRunningDuration(parentDevice);
                this._buildCurrentDaysConsumedNumber(parentDevice);
                // 生成currentMaxPercentage
                var currentRunningDurationPercentage = this.currentRunningDuration / this.limitingConditionFromRunningDuration;
                var currentDaysConsumedNumberPercentage = this.currentDaysConsumedNumber / this.limitingConditionFromDaysNumber;
                this.currentMaxPercentage = Math.max.call(
                    this, currentDaysConsumedNumberPercentage, currentRunningDurationPercentage);
            },
            /**
             * 执行保养
             * @param parentDevice
             * @param remarks
             */
            takeMaintain: function (parentDevice, remarks) {
                parentDevice.refreshInfo();
                var maintainRecord = new MaintainRecord({
                    recordId: DateTimeUtils.getCurrentId(),
                    runningDurationWhileMaintaining: parentDevice.runningDuration,
                    recordRemarks: remarks ? remarks : undefined
                });
                if (!this.maintainRecords || !(this.maintainRecords instanceof Array)) {
                    this.maintainRecords = [];
                }
                this.maintainRecords.unshift(maintainRecord);
                this.lastMaintainInfo = maintainRecord;
                parentDevice.refreshInfo();
            },
            /**
             * 检查属性是否规范
             * @returns {Array}
             */
            checkPropertyFormed: function () {
                var errorProperties = [];
                var checkedProperties = [
                    'maintainName', 'limitingConditionFromRunningDuration',
                    'limitingConditionFromDaysNumber', 'maintainContent'
                ];
                ObjectUtils.whileEmptyObjectProperty(window, this, checkedProperties, function (key) {
                    errorProperties.push(key);
                });
                return errorProperties;
            },
            /**
             * 生产保养统计数据
             * @param device
             * @returns {{totalTimes: Number, totalInYear: number, totalInMonth: number, monthlyAverageTimes: number, annualAverageTimes: number}}
             */
            generateMaintainStatistics: function (device) {
                var records = this.maintainRecords;
                var maintainStatistics = {
                    maintainName: this.maintainName,
                    // 总保养次数
                    totalTimes: records.length,
                    // 当年保养次数
                    totalInYear: 0,
                    // 当月保养次数
                    totalInMonth: 0,
                    // 月均保养次数
                    monthlyAverageTimes: records.length / DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true, 'month'),
                    // 年均保养次数
                    annualAverageTimes: records.length / DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true, 'year')
                };
                ArrayUtils.ergodicArrayObject(this, records, function (record) {
                    var now = new Date();
                    var monthDifference = record.recordTime.getMonth() - now.getMonth();
                    var yearDifference = record.recordTime.getFullYear() - now.getFullYear();
                    if (monthDifference == 0) {
                        maintainStatistics.totalInMonth++;
                    }
                    if (yearDifference == 0) {
                        maintainStatistics.totalInYear++;
                    }
                });

                return maintainStatistics;
            }
        }
        ;
        /**
         * 检查属性是否符合规范
         * @param maintainPlan
         */
        MaintainPlan.checkItFormed = function (maintainPlan) {
            if (!(maintainPlan instanceof MaintainPlan)) {
                throw new TypeError('检查的类型不是MaintainPlan');
            }
            var errorProperties = [];
            var checkedProperties = [
                'maintainName', 'limitingConditionFromRunningDuration',
                'limitingConditionFromDaysNumber', 'maintainContent'
            ];
            ObjectUtils.whileEmptyObjectProperty(window, maintainPlan, checkedProperties, function (key) {
                errorProperties.push(key);
            });
            return errorProperties;
        };
        MaintainPlan.checkPropertyFormed = function (maintainPlans) {
            if (!(maintainPlans instanceof Array)) {
                return [];
            }
            var totalErrorMessages = [];
            ArrayUtils.ergodicArrayObject(this, maintainPlans, function (maintainPlan) {
                var messages = MaintainPlan.checkItFormed(maintainPlan);
                var errorMessages = [];
                ArrayUtils.ergodicArrayObject(this, messages, function (property) {
                    switch (property) {
                        case 'maintainName':
                            errorMessages.push('保养名不能为空');
                            break;
                        case 'limitingConditionFromRunningDuration':
                            errorMessages.push('保养时长不能为空');
                            break;
                        case 'limitingConditionFromDaysNumber':
                            errorMessages.push('保养购买天数不能为空');
                            break;
                        case 'maintainContent':
                            errorMessages.push('保养内容不能为空');
                            break;
                        default:
                            break;
                    }
                });
                if (errorMessages.length > 0) {
                    totalErrorMessages.push(maintainPlan.maintainName + ':[' + errorMessages.toString() + ']')
                }
            });
            return totalErrorMessages;
        };
        /**
         * 转化为保养计划实体（赋予原型链）
         * @param obj{object|Array}
         */
        MaintainPlan.toMaintainPlan = function (obj) {
            if (obj instanceof Array) {
                var originArr = [];
                ArrayUtils.ergodicArrayObject(this, obj, function (value) {
                    originArr.push(this.toMaintainPlan(value));
                });
                return originArr;
            } else if (typeof obj == 'object') {
                var originObj = obj;
                while (obj.__proto__ != null && obj.__proto__ != Object.prototype) {
                    obj = obj.__proto__;
                }
                obj.__proto__ = this.prototype;
                return originObj;
            }
        };
        return MaintainPlan;
    });

    /**
     * 实体对象-模板 {MaintainTemplate}
     */
    app.factory('MaintainTemplate', function (ObjectUtils, MaintainPlan, ArrayUtils) {
        var MaintainTemplate = function (maintainTemplate) {
            this.templateId = null;
            this.templateDiscription = null;
            this.templateName = null;
            this.maintainPlans = [];
            if (maintainTemplate != null) {
                this._initTemplate(maintainTemplate);
            }
        };
        MaintainTemplate.prototype = {
            constructor: MaintainTemplate,
            _initTemplate: function (maintainTemplate) {
                this.templateDiscription = maintainTemplate.templateDiscription;
                this.templateName = maintainTemplate.templateName;
                if (maintainTemplate.maintainPlans != null && maintainTemplate.maintainPlans instanceof Array) {
                    this.maintainPlans = maintainTemplate.maintainPlans;
                }
            },
            toMaintainPlans: function () {
                var plans = ObjectUtils.cloneObject(this.maintainPlans);
                return MaintainPlan.toMaintainPlan(plans);
            },
            checkPropertyFormed: function () {
                var errorProperties = [];
                var checkedProperties = [
                    'templateName'
                ];
                ObjectUtils.whileEmptyObjectProperty(window, this, checkedProperties, function (key) {
                    if (key === 'templateName') {
                        errorProperties.push('模板名不能为空');
                    }
                });
                return errorProperties;
            }
        };
        MaintainTemplate.toMaintainTemplate = function (maintainTemplate) {
            if (maintainTemplate instanceof Array) {
                ArrayUtils.ergodicArrayObject(this, maintainTemplate, function (template) {
                    MaintainTemplate.toMaintainTemplate(template);
                });
                return maintainTemplate;
            } else {
                ObjectUtils.toAimObject(maintainTemplate, MaintainTemplate);
                maintainTemplate.maintainPlans = MaintainPlan.toMaintainPlan(maintainTemplate.maintainPlans);
                delete maintainTemplate.templateId;
                return maintainTemplate;
            }
        };
        return MaintainTemplate;
    });

    /**
     * 实体对象-维修记录
     */
    app.factory('RepairRecord', function (ArrayUtils, logger, DateTimeUtils) {
        var RepairRecord = function (repairRecord) {
            this.recordId = null;
            this.recordTime = null;
            // 设备维修前总运行时长
            this.runningDurationBeforeRepair = null;
            // 该次维修耗用的时间
            this.recordConsumedTimeDuration = null;
            // 该次维修耗用的总金额(￥)
            this.recordConsumedMoney = null;
            this.recordConsumedParts = [];
            if (repairRecord) {
                this._initRepairRecord(repairRecord);
            }
        };
        RepairRecord.prototype = {
            constructor: RepairRecord,
            _initRepairRecord: function (repairRecord) {
                this.recordId = repairRecord.recordId;
                this.recordTime = new Date();
                this.runningDurationBeforeRepair = repairRecord.runningDurationBeforeRepair;
                this.recordConsumedTimeDuration = repairRecord.recordConsumedTimeDuration;
                this.recordConsumedMoney = repairRecord.recordConsumedMoney;
                if (repairRecord.recordConsumedParts != null && repairRecord.recordConsumedParts instanceof Array) {
                    this.recordConsumedParts = repairRecord.recordConsumedParts;
                }
            }
        };
        /**
         * 根据一个设备生成维修统计数据
         * @param device
         * @returns {{totalInMonth: number, totalInYear: number, totalTimes: Number, monthlyRate: number, annuallyRate: number, totalCostInYear: number, totalCostInMonth: number, totalCost: number}}
         */
        RepairRecord.generateRepairStatistics = function (device) {
            var records = device.repairRecords;
            if (!ArrayUtils.isArrayObject(records)) {
                logger.warn('被统计的运行记录列表必须是一个数组');
                return;
            }
            var repairStatistics = {
                // 当年总维修次数
                totalInMonth: 0,
                // 当月总维修次数
                totalInYear: 0,
                // 总维修次数
                totalTimes: records.length,
                // 月度维修率(总维修次数/总月数)
                monthlyRate: records.length / DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true, 'month'),
                // 年度维修率(总维修次数/总年数)
                annuallyRate: records.length / DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true, 'year'),
                // 当年维修总支出
                totalCostInYear: 0,
                // 当月维修总支出
                totalCostInMonth: 0,
                // 维修总支出
                totalCost: 0,
                // 维修总耗用时间
                totalCostTime: 0
            };
            // 若有设备添加前就产生的维修费用，则加到总费用中
            if (device.registerInfo.usedRepairMoney) {
                repairStatistics.totalCost += device.registerInfo.usedRepairMoney;
            }
            // 若有设备添加前就产生的维修时间，则加到总时间中
            if (device.registerInfo.usedRepairTime) {
                repairStatistics.totalCostTime += device.registerInfo.usedRepairTime;
            }
            ArrayUtils.ergodicArrayObject(this, records, function (record) {
                var now = new Date();
                var monthDifference = record.recordTime.getMonth() - now.getMonth();
                var yearDifference = record.recordTime.getFullYear() - now.getFullYear();
                if (monthDifference == 0) {
                    repairStatistics.totalInMonth++;
                    repairStatistics.totalCostInMonth += record.recordConsumedMoney;
                }
                if (yearDifference == 0) {
                    repairStatistics.totalInYear++;
                    repairStatistics.totalCostInYear += record.recordConsumedMoney;
                }
                repairStatistics.totalCost += record.recordConsumedMoney;
                repairStatistics.totalCostTime += record.recordConsumedTimeDuration;
            });

            return repairStatistics;
        };
        return RepairRecord;
    });

    /**
     * 零件实体
     */
    app.factory('Parts', function () {
        var Parts = function (parts) {
            this.partsNo = parts.partsNo;
            this.partsName = parts.partsName;
            this.partsNumber = parts.partsNumber;
        };

        return Parts;
    });

    /**
     * 实体对象-运行记录
     */
    app.factory('RunningRecord', function (logger, ArrayUtils, DateTimeUtils) {
        var RunningRecord = function (runningRecord) {
            this.recordId = null;
            this.recordTime = null;
            this.runningDurationBeforeRunning = null;
            this.recordChangedDuration = null;
            if (runningRecord != null) {
                this._initRunningRecord(runningRecord);
            }
        };
        RunningRecord.prototype = {
            constructor: RunningRecord,
            _initRunningRecord: function (runningRecord) {
                this.recordId = runningRecord.recordId;
                this.recordTime = new Date();
                this.runningDurationBeforeRunning = runningRecord.runningDurationBeforeRunning;
                this.recordChangedDuration = runningRecord.recordChangedDuration;
            }
        };
        /**
         * 通过运行记录生产设备运行的统计数据
         * @param device
         */
        RunningRecord.generateRunningStatistics = function (device) {
            var records = device.runningRecords;
            if (!ArrayUtils.isArrayObject(records)) {
                logger.warn('被统计的运行记录列表必须是一个数组');
                return;
            }
            var runningStatistics = {
                // 距离注册到现在的天数
                daysSinceRegistered: DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true),
                // 日均运行时长（总时长/总天数）
                dailyAverage: (device.runningDuration - device.registerInfo.usedDuration) / (DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true)),
                // 月均运行时长（总时长/总月数）
                monthlyAverage: (device.runningDuration - device.registerInfo.usedDuration) / (DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true, 'month')),
                // 年均运行时长
                annualAverage: (device.runningDuration - device.registerInfo.usedDuration) / (DateTimeUtils.getNowBetweenADay(device.registerInfo.registerTime, true, 'year')),
                // 当月运行总时长
                totalInMonth: 0,
                // 当年运行总时长
                totalInYear: 0
            };

            ArrayUtils.ergodicArrayObject(this, records, function (record) {
                var now = new Date();
                var monthDifference = record.recordTime.getMonth() - now.getMonth();
                var yearDifference = record.recordTime.getFullYear() - now.getFullYear();
                if (typeof record.recordChangedDuration != 'number') {
                    record.recordChangedDuration = parseInt(record.recordChangedDuration);
                }
                if (monthDifference == 0) {
                    runningStatistics.totalInMonth += record.recordChangedDuration;
                }
                if (yearDifference == 0) {
                    runningStatistics.totalInYear += record.recordChangedDuration;
                }
            });
            return runningStatistics;

        };
        return RunningRecord;
    });

    /**
     * 实体对象-保养记录
     */
    app.factory('MaintainRecord', function () {
        var MaintainRecord = function (maintainRecord) {
            this.recordId = null;
            this.recordTime = null;
            // 保养时的总运行时长
            this.runningDurationWhileMaintaining = null;
            // 备注
            this.recordRemarks = null;
            if (maintainRecord != null) {
                this._initMaintainRecord(maintainRecord);
            }
        };
        MaintainRecord.prototype = {
            constructor: MaintainRecord,
            _initMaintainRecord: function (maintainRecord) {
                this.recordId = maintainRecord.recordId;
                this.recordTime = new Date();
                this.runningDurationWhileMaintaining = maintainRecord.runningDurationWhileMaintaining;
                this.recordRemarks = maintainRecord.recordRemarks;
            }
        };
        return MaintainRecord;
    });

    /**
     * 安全事故实体
     */
    app.factory('SafetyAccident', function (DateTimeUtils, ObjectUtils) {
        var SafetyAccident = function (accident) {
            this.accidentId = null;
            delete this.accidentId;
            this.accidentDescription = null;
            this.accidentDetail = null;
            this.accidentAddTime = null;
            this.accidentHappenedTime = null;
            this.accidentLevel = 1;
            this.accidentCostMoney = 0;
            this._init(accident);
        };
        SafetyAccident.prototype = {
            constructor: SafetyAccident,
            _init: function (accident) {
                if (!accident) {
                    return new SafetyAccident();
                }
                this.accidentId = DateTimeUtils.getCurrentId();
                this.accidentDescription = accident.accidentDescription;
                this.accidentDetail = accident.accidentDetail;
                this.accidentHappenedTime = accident.accidentHappenedTime;
                this.accidentAddTime = new Date();
                this.accidentCostMoney = accident.accidentCostMoney;
                this.accidentLevel = accident.accidentLevel;
            },
            checkPropertyFormed: function () {
                var errorProperties = [];
                var checkedProperties = [
                    'accidentDescription',
                    'accidentDetail',
                    'accidentHappenedTime',
                    'accidentCostMoney'
                ];
                ObjectUtils.whileEmptyObjectProperty(window, this, checkedProperties, function (key) {
                    switch (key) {
                        case 'accidentDescription':
                            errorProperties.push('事故描述不能为空');
                            break;
                        case 'accidentDetail':
                            errorProperties.push('事故详情不能为空');
                            break;
                        case 'accidentHappenedTime':
                            errorProperties.push('事故发生时间不能为空');
                            break;
                        case 'accidentCostMoney':
                            errorProperties.push('事故损失金额不能为空');
                            break;
                        default:
                    }
                });
                return errorProperties;
            },
            getLevelDescription: function () {
                switch (this.accidentLevel) {
                    default:
                    case SafetyAccident.NORMAL_LEVEL:
                        return '一般安全事故';
                    case SafetyAccident.MAJOR_LEVEL:
                        return '重大安全事故';
                    case SafetyAccident.SERIOUS_LEVEL:
                        return '特大安全事故';
                }
            }
        };
        SafetyAccident.NORMAL_LEVEL = 1;
        SafetyAccident.MAJOR_LEVEL = 2;
        SafetyAccident.SERIOUS_LEVEL = 3;
        /**
         * 转换原型链为安全事故
         * @param obj
         */
        SafetyAccident.toSafetyAccident = function (obj) {
            return ObjectUtils.toAimObject(obj, SafetyAccident, {
                accidentLevel: 1
            })
        };
        return SafetyAccident;
    });
})
;